package com.example.webwork.util;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;

import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

// MyBatis拦截器（需手写）也可基于JDBC实现
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class TableRoutingInterceptor implements Interceptor {

        // todo 实现逻辑
        // 分片键字段名
        private static final String SHARDING_KEY = "id";

        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            Object[] args = invocation.getArgs();
            MappedStatement ms = (MappedStatement) args[0];
            Object parameter = args[1];
            BoundSql boundSql = ms.getBoundSql(parameter);


            Long shardValue = extractShardValue(parameter);
            if (shardValue == null) {
                throw new IllegalArgumentException("分片键id未找到");
            }


            String[] routeResult = calculateRoute(shardValue);
            String dbKey = routeResult[0];
            String tableSuffix = routeResult[1];




            String newSql = rewriteTableName(boundSql.getSql(), tableSuffix);
            updateBoundSql(boundSql, newSql);

            return invocation.proceed();
        }


        private Long extractShardValue(Object parameter) {
            if (parameter instanceof Map) {
                return (Long) ((Map<?,?>) parameter).get(SHARDING_KEY);
            } else {
                try {
                    Field idField = parameter.getClass().getDeclaredField(SHARDING_KEY);
                    idField.setAccessible(true);
                    return (Long) idField.get(parameter);
                } catch (Exception e) {
                    return null;
                }
            }
        }


        private String[] calculateRoute(Long id) {
            if (id % 4 == 0) {
                return new String[]{"db0", "user01"};
            } else if (id % 2 == 0) {
                return new String[]{"db1", "user02"};
            } else {
                throw new IllegalArgumentException("未定义的分片路由规则，id=" + id);
            }
        }

        // SQL重写（精准替换表名）
        private String rewriteTableName(String originalSql, String tableSuffix) {
            return originalSql.replaceAll("(?i)user(_\\w+)?\\b", "user" + tableSuffix);
        }


        private void updateBoundSql(BoundSql boundSql, String newSql) {
            MetaObject metaObject = SystemMetaObject.forObject(boundSql);
            metaObject.setValue("sql", newSql);
        }

        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }

        @Override
        public void setProperties(Properties properties) {}

    }